/**
 * 
 */
package org.gbif.biogarage.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.lucene.document.Document;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.ConstantScoreQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.PrefixFilter;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.Searcher;
import org.apache.lucene.search.TopDocCollector;

/**
 * @author tim
 */
public class LuceneKeyValueAutocompleteServlet extends HttpServlet {
	final static String CALLBACK = "callback";
	IndexReader reader;
	Searcher searcher;
	String param = "prefix";
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		String prefix = req.getParameter(param);
		String callback = req.getParameter(CALLBACK);
		List<String> results = new LinkedList<String>();
		if (prefix!=null && reader!=null) {
			System.out.println("Searching for: '" + prefix + "'");
			
			Term term = new Term("name", prefix.toLowerCase());
			// wilcards cannot be scord or else there is simply too many options
			Query query = new ConstantScoreQuery(new PrefixFilter(term));
			
			
			System.out.println("Searching...");
			long time = System.currentTimeMillis();
			TopDocCollector collector = new TopDocCollector(25);
			searcher.search(query, collector);
			ScoreDoc[] hits = collector.topDocs().scoreDocs;
			System.out.println("hits: " + hits.length);
			
			for (int i = 0; i < hits.length; i++) {
				Document doc = searcher.doc(hits[i].doc);
				String id = doc.get("id");
				if (id != null) {
					results.add(doc.get("name") + "," + id);
				}
			}
			System.out.println("Search returned in " + (System.currentTimeMillis() - time) + " msecs");
		}
		Collections.sort(results);
		
		boolean isFirst=true;
		PrintWriter out = resp.getWriter();
		if (callback!=null && callback.length()>1){
			out.print(callback + "([");
		}else{
			out.print("[");			
		}
		for (String s : results) {
			if (!isFirst){
				out.print(",");
				isFirst=false;
			}
			out.print("{");
			out.print(s);
			out.print("}");
		}
		if (callback!=null && callback.length()>1){
			out.print("])");
		}else{
			out.print("]");
		}
		out.flush();
		out.close();
	}

	@Override
	public void init() throws ServletException {
		String indexDir = getInitParameter("lucene-index-directory");
		if (indexDir != null) {
			try {
				System.out.println("Using index directory: " + indexDir);
				reader = IndexReader.open(indexDir);
				searcher = new IndexSearcher(reader);				
			} catch (Exception e) {
				throw new ServletException("Cannot create autocomplete", e);
			}
		} else {
			throw new ServletException("Must specify a lucene-index-directory");
		}
		super.init();
	}

	@Override
	public void destroy() {
		if (searcher != null) {
			try {
				searcher.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		if (reader != null) {
			try {
				reader.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		super.destroy();
	}
	
	
	
}
